import { svgPathProperties } from "svg-path-properties";
import Tabs from "@/components/Tabs";
import Taro from "@tarojs/taro";
import {
  useRef,
  useEffect,
  forwardRef,
  useState,
  useImperativeHandle,
} from "react";
import blocks from "@/utils/motions-data";
import { Canvas, View } from "@tarojs/components";
import TagCheckbox from "../TagCheckbox";
import "./index.less";

// 缓存路径点数据
const pathPointCache = new Map<string, any[]>();

// 预计算路径点并缓存
const precomputePathPoints = (path: string) => {
  if (pathPointCache.has(path)) {
    return pathPointCache.get(path)!;
  }

  const properties = new svgPathProperties(path);
  const totalLength = properties.getTotalLength();
  const points = [];

  // 优化采样点数量（根据路径长度动态调整）
  // const step = Math.max(1, Math.ceil(totalLength / 50));

  for (let i = 0; i <= totalLength; i += 1) {
    points.push(properties.getPointAtLength(i));
  }

  // 添加终点确保路径闭合
  // points.push(properties.getPointAtLength(totalLength));

  pathPointCache.set(path, points);
  return points;
};

// 预先计算并缓存所有路径点
const precomputeAllPaths = () => {
  // 预计算外轮廓
  blocks.outluine.forEach((path) => {
    precomputePathPoints(path);
  });

  // 预计算肌肉路径
  blocks.muscles.forEach((muscle) => {
    if (muscle.paths) {
      muscle.paths.forEach((path) => precomputePathPoints(path));
    }
    if (muscle.children) {
      muscle.children.forEach((child) => {
        child.paths.forEach((path) => precomputePathPoints(path));
      });
    }
  });
};
precomputeAllPaths();

const getPathsfromKey = (keys: string[]) => {
  const paths: string[][] = [];
  for (const key of keys) {
    paths.push(...blocks.keyToPaths[key].paths);
  }
  return paths;
};

const drawpath = (canvas, path, closePath = true) => {
  canvas.beginPath();
  const points = precomputePathPoints(path);

  if (points.length > 0) {
    canvas.moveTo(points[0].x, points[0].y);

    for (let i = 1; i < points.length; i++) {
      canvas.lineTo(points[i].x, points[i].y);
    }
  }

  if (closePath) {
    canvas.closePath();
  } else {
    canvas.closePath = () => {};
  }
};

const DEFAULT_COLOR = "#f3f1f7";
const MAIN_COLOR = "#3648b1";
const MINOR_COLOR = "#717fd0";

const radio = [
  { label: "目标肌群", value: 0 },
  { label: "协助肌群", value: 1 },
];

type IProps = {
  main: string[];
  minor: string[];
};

const MuscleCanvas = forwardRef((props: IProps, ref) => {
  const ctxRef = useRef<Taro.CanvasContext>();
  const [type, setType] = useState(0);
  const [main, setMain] = useState(props.main);
  const [minor, setMinor] = useState(props.minor);

  useImperativeHandle(ref, () => ({
    getMain: () => main,
    getMinor: () => minor,
  }));

  const fillPaths = (paths, color = DEFAULT_COLOR) => {
    if (paths.length === 0) return;
    if (!ctxRef.current) return;
    for (const path of paths) {
      drawpath(ctxRef.current, path);
      ctxRef.current.fillStyle = color;
      ctxRef.current.fill();
    }
  };
  const diffdraw = (oldArr, newArr, activeColor = MAIN_COLOR) => {
    const set2 = new Set(newArr);
    const del = oldArr.filter((item) => !set2.has(item));
    const set1 = new Set(oldArr);
    const add = newArr.filter((item) => !set1.has(item));

    const oldPaths = getPathsfromKey(del);
    const newPaths = getPathsfromKey(add);
    fillPaths(oldPaths);
    fillPaths(newPaths, activeColor);
  };

  useEffect(() => {
    initCanvas();

    return () => {
      if (ctxRef.current) {
        ctxRef.current = null;
      }
    };
  }, []);

  const handleChangeType = (value) => {
    setType(value);
  };

  const handleChangeMuscle = (value) => {
    let oldMain = main;
    let oldMinor = minor;

    if (type === 0) {
      if (minor.includes(value)) {
        let newMinor = minor.filter((key) => key !== value);
        setMinor(newMinor);
        diffdraw(oldMinor, newMinor, MINOR_COLOR);
      }
      setMain(value);
      diffdraw(oldMain, value, MAIN_COLOR);
    } else {
      if (main.includes(value)) {
        let newMain = main.filter((key) => key !== value);
        setMain(newMain);
        diffdraw(oldMain, newMain, MAIN_COLOR);
      }
      setMinor(value);
      diffdraw(oldMinor, value, MINOR_COLOR);
    }
  };

  const initCanvas = async () => {
    const query = Taro.createSelectorQuery();
    const dpr = Taro.getSystemInfoSync().pixelRatio;
    query
      .select("#muscleCanvas")
      .fields({
        node: true,
        size: true,
      })
      .exec(function (res) {
        const canvas = res[0].node;
        const designWidth = 809;
        const designHeight = 768;
        // 设置物理像素尺寸
        canvas.width = res[0].width * dpr;
        canvas.height = res[0].height * dpr;
        const scale = Math.min(
          canvas.width / designWidth,
          canvas.height / designHeight
        );

        // 调整坐标系缩放
        const ctx = canvas.getContext("2d");
        ctx.font = "24px serif";
        const offsetX = (canvas.width - designWidth) / 2 / dpr;

        ctx.fillText("正面", 200 * scale + offsetX + 30, 36);
        ctx.fillText("背面", 500 * scale + offsetX + 30, 36);

        ctx.scale(scale, scale);

        ctxRef.current = ctx;

        // outluine
        blocks.outluine.forEach((path) => {
          drawpath(ctx, path, false);
          ctx.strokeStyle = "#000";
          ctx.stroke();
        });

        //muscles
        for (const muscle of blocks.muscles) {
          if (muscle.paths) fillPaths(muscle.paths);
          if (muscle.children) {
            for (const m of muscle.children) fillPaths(m.paths);
          }
        }

        if (main.length || minor.length) {
          diffdraw([], main, MAIN_COLOR);
          diffdraw([], minor, MINOR_COLOR);
        }

      });
  };

  return (
    <View className="muscle-container">
      <View
        style={{
          margin: "0 16px 8px 16px",
          textAlign: "center",
        }}
      >
        <Tabs options={radio} onChange={handleChangeType} value={type} />
      </View>
      <TagCheckbox
        values={type ? minor : main}
        onChange={handleChangeMuscle}
        options={blocks.options}
        isRadio={type === 0}
        className="small"
        style={{
          display: "flex",
          flexWrap: "wrap",
          justifyContent: "flex-start",
        }}
      />
      <Canvas
        type="2d"
        id="muscleCanvas"
        style={{ width: "100vw", height: "50vh" }}
      />
    </View>
  );
});

export default MuscleCanvas;
